/*
 * Copyright (C) 2010-2012 Susanta Tewari
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package genomemap.cef.pui;

import cef.event.Event;
import cef.event.TestModelIDEvent;
import cef.pui.EventConstructionException;
import cef.pui.EventImpl;
import cef.pui.pob.Builder;
import cef.pui.pob.BuilderException;
import commons.core.Generator;
import commons.core.LikelihoodComputer;
import commons.core.MultiLHoodComputer;
import commons.core.Simulator;
import commons.util.ListUtil;
import commons.util.base.Converter;
import genomemap.cef.pui.pob.Builders_Gen;
import genomemap.data.TAB08Data;
import genomemap.model.TAB08;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static cef.pui.pob.Builders.of_Integer;
import static genomemap.cef.pui.pob.Builders_Gen.*;

/**
 * Implements {@code TestModelIDEvent} using the following properties.
 * <ul>
 *     <li>
 *         {@code genomemap.builder.TAB08.delegate = fully qualified builder class name for the same value type} <br/>OR<br/>
 *         {@code genomemap.builder.TAB08Data.url = tab08data:xml//URL }<a href="genomemap/cef/pui/pob/doc-files/tab08-data.xml.txt">file format</a>, must accompany the <a href="genomemap/cef/pui/pob/doc-files/TAB08Data.xsd.txt">schema</a>
 *     </li>
 *     <li>{@code genomemap.builder.TAB08Lhood.implCode = tab08:rla | tab08:sfa}</li>
 *     <li>{@code (opt. default 20) genomemap.builder.sampleSize = integer value}</li>
 * </ul>
 *
 * @author Susanta Tewari
 * @version 1.3.0
 * @history Created on Sep 30, 2012.
 * @since 1.3.0
 */
public final class TestTAB08ModelIDEventImpl extends EventImpl
        implements TestModelIDEvent<TAB08, TAB08Data> {

    /** model builder */
    private final Builder<TAB08> m_b;

    /** sample size builder */
    private final Builder<Integer> sample_size_b;

    /** model count builder */
    private final Builder<Integer> model_count_b;

    /** model generator builder */
    private final Builder<Generator.MODEL<TAB08, TAB08>> mg_b;

    /** data simulator builder */
    private final Builder<Simulator.DATA<TAB08, TAB08Data>> ds_b;

    /** LikelihoodComputer builder for TAB08Data */
    private final Builder<LikelihoodComputer<TAB08Data>> lc_b;

    public TestTAB08ModelIDEventImpl(final Properties props) throws EventConstructionException {

        super(props);

        super.processEventProperties(getImplementedEventInterfaces());


        // builder: model
        m_b = Builder.of_delegate(of_Data_TAB08_File(props, null),
                                  new Converter<TAB08Data, TAB08>() {

            @Override
            public TAB08 convert(TAB08Data input) {
                return input.getModel();
            }

        });


        // builder: sample size, modelCount
        sample_size_b = cef.pui.pob.Builders.of_Integer(props, "sampleSize", "genomemap.builder");
        model_count_b = of_Integer(props, "modelCount", "genomemap.builder");


        // builders: other
        mg_b = of_Generator_Model_TAB08(props, null);
        ds_b = of_Simulator_Data_TAB08(props, null);
        lc_b = Builders_Gen.of_LHoodComputer_TAB08(props, null);
    }

    @Override
    public TAB08 getInputModel() {
        return m_b.build();
    }

    @Override
    public int getModelCount() {
        return model_count_b.canBuild() ? model_count_b.build() : 50;
    }

    @Override
    public String getModelDescription(final TAB08 m) {
        return m.getGenes().toString();
    }

    @Override
    public BigDecimal getModelDistance(final TAB08 m1, final TAB08 m2) {
        return new BigDecimal(ListUtil.countDiff(m1.getGenes(), m2.getGenes()));
    }

    @Override
    public int getSampleSize() {
        return sample_size_b.canBuild() ? sample_size_b.build() : 20;
    }

    @Override
    protected List<Class<? extends Event>> getImplementedEventInterfaces() {

        final List<Class<? extends cef.event.Event>> result = new ArrayList<>(2);

        result.add(TestModelIDEvent.class);
        result.add(Event.class);

        return result;
    }

    @Override
    public Generator.MODEL<TAB08, TAB08> getModelGenerator() throws BuilderException {
        return mg_b.build();
    }

    @Override
    public Simulator.DATA<TAB08, TAB08Data> getDataSimulator() throws BuilderException {
        return ds_b.build();
    }

    /**
     * @return Provides a serial implementation as described in {@link MultiLHoodComputer.ofDefault()}.
     */
    @Override
    public MultiLHoodComputer<TAB08, TAB08Data, TAB08Data> getMultiLHoodComputer() {
        return MultiLHoodComputer.ofDefault(lc_b.build());
    }
}
